<?php declare(strict_types=1);

/**
 * @author      guosir
 * @copyright   2023-2025 owner
 **/

namespace Srv\Apps\Apis\Develop\Ctl;

use Srv\Apps\Apis\Admin\Ctl\AdminCtl;
use Srv\Apps\Apis\Common\DefCtl\DefUserRegTypeCtl;
use Srv\Apps\Apis\Common\IdxCtl\IdxIp;
use Srv\Apps\Apis\User\Ctl\UserCtl;
use Srv\Apps\Proto\DTO\Develop\ApiRequestListDTO;
use Srv\Apps\Proto\DTO\Develop\AdmRequestListDTO;
use Srv\Apps\Proto\Enum\Develop\RequestCategoryEnum;
use Srv\Apps\Proto\Enum\Develop\RequestResultEnum;
use Srv\Apps\Proto\VO\Admin\AdmUserInfoBasicVO;
use Srv\Apps\Proto\VO\Develop\ApiRequestListVO;
use Srv\Apps\Proto\VO\Develop\ApiRequestVO;
use Srv\Apps\Proto\VO\Develop\AdmRequestListVO;
use Srv\Apps\Proto\VO\Develop\AdmRequestVO;
use Srv\Apps\Proto\VO\User\UserInfoBasicVO;
use Srv\Libs\Common\CommArray;
use Srv\Libs\Frame\ControllerAbstract;
use Srv\Libs\Frame\Page;
use Srv\Libs\Storage\DataMysql;
use Srv\Libs\Tools\IpAddr;

final class RequestRecordCtl extends ControllerAbstract
{
    private ?DataMysql $DbAuto              = null;     // DB-Write

    /**
     * @return static
     * tag
     */
    final public static function tag():self
    {
        $thisObject                         = self::tagGet();
        if($thisObject instanceof self){
            $thisObject->DbAuto             = self::getDbAuto();
        }
        return $thisObject;
    }

    /**
     * @param Page $Page
     * @param array $whereData
     * @return AdmRequestListVO|null
     * getAdmRequestList
     */
    public function getAdmRequestList(Page $Page, array $whereData): ?AdmRequestListVO
    {
        $limitString        = $Page->getLimitString();
        $whereString        = ' WHERE 1 ';
        $whereSearch        = false;
        // 检索条件
        if(count($whereData) > 0)foreach ($whereData as $key => $val){
            switch ($key){
                case AdmRequestListDTO::_rrId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_id='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
                case AdmRequestListDTO::_category:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_category='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
                case AdmRequestListDTO::_userId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
                case AdmRequestListDTO::_userName:
                    $tempSql        = 'SELECT auir_id FROM '.$this->DbAuto->getTableNameAll('adm_user_record').' WHERE auir_delete=0 AND auir_name LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id IN('. $tempSql .')';
                    !$whereSearch && $whereSearch   = true;
                    break;
                case AdmRequestListDTO::_mobile:
                    $tempSql        = 'SELECT auir_id FROM '.$this->DbAuto->getTableNameAll('adm_user_record').' WHERE auir_delete=0 AND auir_mobile LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id IN('. $tempSql .')';
                    !$whereSearch && $whereSearch   = true;
                    break;
                case AdmRequestListDTO::_devId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_dev_id=\''. $this->DbAuto->getRealEscapeString($val).'\'';
                    !$whereSearch && $whereSearch   = true;
                    break;
                case AdmRequestListDTO::_path:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_path LIKE \''. $this->DbAuto->getRealEscapeString($val).'%\'';
                    !$whereSearch && $whereSearch   = true;
                    break;
                case AdmRequestListDTO::_result:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_result='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
                case AdmRequestListDTO::_resultTime:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_result_time>='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
                case AdmRequestListDTO::_createTimeStart:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_create_time>='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
                case AdmRequestListDTO::_createTimeStop:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_create_time<='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
            }
        }
        $isFail                 = false;
        $sql                    = 'SELECT SQL_CALC_FOUND_ROWS rr_id, rr_category, user_id, rr_nonce, rr_dev_id, rr_ip, rr_path, rr_req_header, rr_req_body, rr_rsp_body, rr_result, rr_result_time, rr_result_size, rr_create_time FROM '.$this->DbAuto->getTableNameAll('adm_request_record').$whereString.' ORDER BY rr_id DESC '.$limitString;
        $list                   = $this->DbAuto->getData($sql, $isFail);
        if($whereSearch){
            $totalNum           = $this->DbAuto->getDataInt('SELECT FOUND_ROWS() as num', 'num');
        }else{
            $totalNum           = 1000000;
        }
        if($isFail) return null;
        $AdmRequestVOList       = [];
        if(CommArray::isForeach($list)){
            $userIdList             = array_map('intval', array_column($list, 'user_id'));
            $AdmUserInfoBasicList   = AdminCtl::tag()->getAdmUserInfoBasicBatch($userIdList);
            foreach($list as $item){
                $rrIdItem           = intval($item['rr_id']);
                if($rrIdItem < 1) continue;
                $AdmRequestVO       = $this->getAdmRequestVO($item);
                if(!($AdmRequestVO instanceof AdmRequestVO)) continue;
                $AdmUserInfoBasicVO = $AdmUserInfoBasicList[intval($item['user_id']??0)]??null;
                if($AdmUserInfoBasicVO instanceof AdmUserInfoBasicVO) $AdmRequestVO->setAdmUserInfoBasic($AdmUserInfoBasicVO);
                $AdmRequestVOList[] = $AdmRequestVO;
            }
        }
        $AdmRequestListVO           = new AdmRequestListVO();
        $AdmRequestListVO->setList($AdmRequestVOList);
        $AdmRequestListVO->setPage($Page->getPageVO($totalNum));
        return $AdmRequestListVO;
    }

    /**
     * @param array $requestRecord
     * @return AdmRequestVO|null
     * getAdmRequestVO
     */
    public function getAdmRequestVO(array $requestRecord): ?AdmRequestVO
    {
        $rrId               = intval($requestRecord['rr_id']??0);
        if($rrId < 1) return null;
        $AdmRequestVO       = new AdmRequestVO();
        $AdmRequestVO->setRrId($rrId);
        $AdmRequestVO->setCategory(RequestCategoryEnum::parseValue($requestRecord['rr_category']));
        $AdmRequestVO->setNonce(intval($requestRecord['rr_nonce']));
        $AdmRequestVO->setDevId($requestRecord['rr_dev_id']);
        $IpString           = IdxIp::tag()->getIpStrByIntStr($requestRecord['rr_ip']);
        $ipArea             = IpAddr::getLocationInfo($IpString);
        $AdmRequestVO->setIpString($IpString.'('.($ipArea['country']??'').')');
        $AdmRequestVO->setPath($requestRecord['rr_path']);
        $AdmRequestVO->setReqHeader($requestRecord['rr_req_header']);
        $AdmRequestVO->setReqBody($requestRecord['rr_req_body']);
        $AdmRequestVO->setRspBody($requestRecord['rr_rsp_body']);
        $AdmRequestVO->setResult(RequestResultEnum::parseValue($requestRecord['rr_result']));
        $AdmRequestVO->setResultTime(intval($requestRecord['rr_result_time']));
        $AdmRequestVO->setResultSize(intval($requestRecord['rr_result_size']));
        $AdmRequestVO->setCreateTime(intval($requestRecord['rr_create_time']));
        return $AdmRequestVO;
    }

    /**
     * @param Page $Page
     * @param array $whereData
     * @return ApiRequestListVO|null
     * getApiRequestList
     */
    public function getApiRequestList(Page $Page, array $whereData): ?ApiRequestListVO
    {
        $limitString        = $Page->getLimitString();
        $whereString        = ' WHERE 1 ';
        $whereSearch        = false;
        // 检索条件
        if(count($whereData) > 0)foreach ($whereData as $key => $val){
            switch ($key){
                case ApiRequestListDTO::_rrId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_id='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
                case ApiRequestListDTO::_category:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_category='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
                case ApiRequestListDTO::_userId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
                case ApiRequestListDTO::_idNum:
                    if(strlen($val) > 10 && is_numeric($val)){
                        $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id='. intval($val);
                    }else{
                        $tempSql        = 'SELECT user_id FROM '.$this->DbAuto->getTableNameAll('user_info').' WHERE usi_delete=0 AND usi_idnum LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                        $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id IN('. $tempSql .')';
                    }
                    !$whereSearch && $whereSearch   = true;
                    break;
                case ApiRequestListDTO::_mobile:
                    $durtId         = DefUserRegTypeCtl::tag()->getIdByKey(DefUserRegTypeCtl::KEY_REG_MOBILE);
                    $tempSql        = 'SELECT DISTINCT user_id FROM '.$this->DbAuto->getTableNameAll('user_bind_record').' WHERE usbr_delete=0 AND usbr_enable=1 AND durt_id='.$durtId.' AND usbr_openid LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id IN('. $tempSql .')';
                    !$whereSearch && $whereSearch   = true;
                    break;
                case ApiRequestListDTO::_devId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_dev_id=\''. $this->DbAuto->getRealEscapeString($val).'\'';
                    !$whereSearch && $whereSearch   = true;
                    break;
                case ApiRequestListDTO::_path:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_path LIKE \''. $this->DbAuto->getRealEscapeString($val).'%\'';
                    !$whereSearch && $whereSearch   = true;
                    break;
                case ApiRequestListDTO::_result:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_result='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
                case ApiRequestListDTO::_resultTime:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_result_time>='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
                case ApiRequestListDTO::_createTimeStart:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_create_time>='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
                case ApiRequestListDTO::_createTimeStop:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'rr_create_time<='. intval($val);
                    !$whereSearch && $whereSearch   = true;
                    break;
            }
        }
        $isFail                 = false;
        $sql                    = 'SELECT SQL_CALC_FOUND_ROWS rr_id, rr_category, user_id, rr_nonce, rr_dev_id, rr_ip, rr_path, rr_req_header, rr_req_body, rr_rsp_body, rr_result, rr_result_time, rr_result_size, rr_create_time FROM '.$this->DbAuto->getTableNameAll('request_record').$whereString.' ORDER BY rr_id DESC '.$limitString;
        $list                   = $this->DbAuto->getData($sql, $isFail);
        if($whereSearch){
            $totalNum           = $this->DbAuto->getDataInt('SELECT FOUND_ROWS() as num', 'num');
        }else{
            $totalNum           = 1000000;
        }
        if($isFail) return null;
        $ApiRequestVOList       = [];
        if(CommArray::isForeach($list)){
            $userIdList             = array_map('intval', array_column($list, 'user_id'));
            $UserInfoBasicVOList    = UserCtl::tag()->getUserInfoBasicBatch($userIdList);
            foreach($list as $item){
                $rrIdItem           = intval($item['rr_id']);
                if($rrIdItem < 1) continue;
                $ApiRequestVO       = $this->getApiRequestVO($item);
                if(!($ApiRequestVO instanceof ApiRequestVO)) continue;
                $UserInfoBasicVO    = $UserInfoBasicVOList[intval($item['user_id']??0)]??null;
                if($UserInfoBasicVO instanceof UserInfoBasicVO) $ApiRequestVO->setUserInfoBasic($UserInfoBasicVO);
                $ApiRequestVOList[] = $ApiRequestVO;
            }
        }
        $ApiRequestListVO           = new ApiRequestListVO();
        $ApiRequestListVO->setList($ApiRequestVOList);
        $ApiRequestListVO->setPage($Page->getPageVO($totalNum));
        return $ApiRequestListVO;
    }

    /**
     * @param array $requestRecord
     * @return ApiRequestVO|null
     * getApiRequestVO
     */
    public function getApiRequestVO(array $requestRecord): ?ApiRequestVO
    {
        $rrId               = intval($requestRecord['rr_id']??0);
        if($rrId < 1) return null;
        $ApiRequestVO       = new ApiRequestVO();
        $ApiRequestVO->setRrId($rrId);
        $ApiRequestVO->setCategory(RequestCategoryEnum::parseValue($requestRecord['rr_category']));
        $ApiRequestVO->setNonce(intval($requestRecord['rr_nonce']));
        $ApiRequestVO->setDevId($requestRecord['rr_dev_id']);
        $IpString           = IdxIp::tag()->getIpStrByIntStr($requestRecord['rr_ip']);
        $ipArea             = IpAddr::getLocationInfo($IpString);
        $ApiRequestVO->setIpString($IpString.'('.($ipArea['country']??'').')');
        $ApiRequestVO->setPath($requestRecord['rr_path']);
        $ApiRequestVO->setReqHeader($requestRecord['rr_req_header']);
        $ApiRequestVO->setReqBody($requestRecord['rr_req_body']);
        $ApiRequestVO->setRspBody($requestRecord['rr_rsp_body']);
        $ApiRequestVO->setResult(RequestResultEnum::parseValue($requestRecord['rr_result']));
        $ApiRequestVO->setResultTime(intval($requestRecord['rr_result_time']));
        $ApiRequestVO->setResultSize(intval($requestRecord['rr_result_size']));
        $ApiRequestVO->setCreateTime(intval($requestRecord['rr_create_time']));
        return $ApiRequestVO;
    }
}